//===============================================================================
// Copyright (C) 2008 Charles River Media. All rights reserved.
// 
// Catmull-Clark subdivision surface viewer program
//
// The developer of the code is
// Gyorgy Antal <gyantal@gmail.com>
//
// Contributor(s):
// Laszlo Szirmay-Kalos <szirmay@iit.bme.hu>
//
// The software was developed for the chapter 
// "Fast Evaluation of Subdivision Surfaces on DirectX10 Graphics Hardware"
// of the book ShaderX 6: Advanced Rendering Techniques, 
// edited by Wolfgang Engel,
// the appropriate section edited by Tom Forsyth. 
//
// The files are provided without support, instruction, or implied warranty of any
// kind.  Charles River Media makes no guarantee of its fitness for a particular purpose and is
// not liable under any circumstances for any damages or loss whatsoever arising
// from the use or inability to use this file or items derived from it.
//===============================================================================
// File: Obj.h
//
// Description:
//===============================================================================

#include "scanner.h"
#include "vector.h"

//---------------------------------------------------------------
//      SpecialCharTable
//---------------------------------------------------------------
extern SpecialChar specials[];

//---------------------------------------------------------------
//      KeywordTable
//---------------------------------------------------------------
extern Keyword keywords[];

//---------------------------------------------------------------
// SCANNER STATE MACHINE                                         
// Separates input stream into tokens
//---------------------------------------------------------------
class ObjScanner : public Scanner {
//---------------------------------------------------------------
public:
    ObjScanner(char * n);
    BOOL IsCommentBegin(char c) { return c == '#'; }
	BOOL IsCommentEnd(char c)	  { return c == '\n'; } 
};

#define MAXVERTEX	262144
//---------------------------------------------------------------
// OBJ Parser
//---------------------------------------------------------------
class ObjParser : public ObjScanner {
	public:
	float	scale;
	Vector vertices[ MAXVERTEX * 3 ];
	Vector vertex_normals[ MAXVERTEX * 3 ];
	Vector vertex_textures[ MAXVERTEX * 3 ];

	int	  nvertex, ntexture, nnormal, npoly_vertex;
	int	  read_ptr;

	int	  poly_vertexInd[ MAXVERTEX ];
	int   poly_normalInd[ MAXVERTEX ];
	int	  poly_textureInd[ MAXVERTEX ];
	float minX, maxX, minY, maxY, minZ, maxZ;
	
public:
	ObjParser(char * n) : ObjScanner(n) { 
		read_ptr = 0;
		nvertex = ntexture = nnormal = npoly_vertex = 0; 
		scale = 1.0f; 
	}

	float GetBoundingSphere() {
		float radius = (float)fabs(maxX);
		if (fabs(minX) > radius) radius = fabs(minX);
		if (fabs(maxY) > radius) radius = fabs(maxY);
		if (fabs(minY) > radius) radius = fabs(minY);
		if (fabs(maxZ) > radius) radius = fabs(maxZ);
		if (fabs(minZ) > radius) radius = fabs(minZ);
		return radius;
	}
	
	BOOL NextPolygon() {
		if (read_ptr < npoly_vertex) return TRUE;
		else {
			read_ptr = 0;
			return FALSE;
		}
	}

	void NextVertex() { read_ptr++; }

	Vector * Vertex() {
		int idx = poly_vertexInd[ read_ptr ];
		if (idx > 0) return &vertices[ idx - 1 ];
		else		   return NULL;
	}

	Vector * Normal() {
		int idx = poly_normalInd[ read_ptr ];
		if (idx > 0) return &vertex_normals[ idx - 1 ];
		else		   return NULL;
	}

	Vector * Texture() {
		int idx = poly_textureInd[ read_ptr ];
		if (idx > 0) return &vertex_textures[ idx - 1 ];
		else		   return NULL;
	}

	void ParseFile();
	void ParseVertex();
	void ParseVertexNormal();
	void ParseVertexTexture();
	void ParseGroup();
	void ParseFace();
	void ParseMaterial();
	void ParseSurface();
	void ParseMaterialLib();
};

